package com.mofum.msdom.excel.annotation.parser.impl;

import com.mofum.msdom.excel.annotation.ATSheetColumnIndex;
import com.mofum.msdom.excel.annotation.parser.AnnotationParser;
import com.mofum.msdom.excel.metadata.MPSheetColumnIndex;
import com.mofum.msdom.excel.utils.ReflectUtils;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class ATSheetColumnIndexParser<T> implements AnnotationParser<T, MPSheetColumnIndex> {

    public Map<Field, MPSheetColumnIndex> parseField(T o) {

        Map<Field, MPSheetColumnIndex> map = new HashMap<Field, MPSheetColumnIndex>();

        Field[] fields = ReflectUtils.convertToClass(o).getDeclaredFields();

        for (Field field : fields) {

            if (field.isAnnotationPresent(ATSheetColumnIndex.class)) {

                ATSheetColumnIndex atSheetColumnIndex = field.getAnnotation(ATSheetColumnIndex.class);

                map.put(field, parse(atSheetColumnIndex));

            }

        }

        return map;
    }

    public Map<Type, MPSheetColumnIndex> parseType(T o) {

        Map<Type, MPSheetColumnIndex> map = new HashMap<Type, MPSheetColumnIndex>();

        Class<T> clazz = ReflectUtils.convertToClass(o);

        if (clazz.isAnnotationPresent(ATSheetColumnIndex.class)) {

            ATSheetColumnIndex atSheetColumnIndex = clazz.getAnnotation(ATSheetColumnIndex.class);

            map.put(clazz, parse(atSheetColumnIndex));

        }

        return map;
    }

    public Map<Method, MPSheetColumnIndex> parseMethod(T o) {

        Map<Method, MPSheetColumnIndex> map = new HashMap<Method, MPSheetColumnIndex>();

        Method[] methods = ReflectUtils.convertToClass(o).getDeclaredMethods();

        for (Method method : methods) {

            if (method.isAnnotationPresent(ATSheetColumnIndex.class)) {

                ATSheetColumnIndex atSheetColumnIndex = method.getAnnotation(ATSheetColumnIndex.class);

                map.put(method, parse(atSheetColumnIndex));

            }

        }

        return map;
    }

    public Map<Method, List<MPSheetColumnIndex>> parseParams(T o) {

        Map<Method, List<MPSheetColumnIndex>> map = new HashMap<Method, List<MPSheetColumnIndex>>();

        Method[] methods = ReflectUtils.convertToClass(o).getMethods();

        for (Method method : methods) {

            List<MPSheetColumnIndex> list = new ArrayList<MPSheetColumnIndex>();

            Annotation[][] parameterAnnotations = method.getParameterAnnotations();

            for (Annotation[] parameterAnnotation : parameterAnnotations) {
                for (Annotation annotation : parameterAnnotation) {
                    if (annotation instanceof ATSheetColumnIndex) {
                        ATSheetColumnIndex atSheetColumnIndex = (ATSheetColumnIndex) annotation;
                        list.add(parse(atSheetColumnIndex));
                    }
                }
            }

            map.put(method, list);
        }

        return map;
    }


    public MPSheetColumnIndex parse(ATSheetColumnIndex atSheetColumnIndex) {
        MPSheetColumnIndex mpSheetColumnIndex = new MPSheetColumnIndex();
        mpSheetColumnIndex.setIndex(atSheetColumnIndex.index());
        mpSheetColumnIndex.setValue(atSheetColumnIndex.value());
        return mpSheetColumnIndex;
    }
}
